// MValue.h: Definition of the CMValue class
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_MVALUE_H__1B6ED7CB_EB38_11D1_BF0B_0000B4560A15__INCLUDED_)
#define AFX_MVALUE_H__1B6ED7CB_EB38_11D1_BF0B_0000B4560A15__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#include "resource.h"       // main symbols

/////////////////////////////////////////////////////////////////////////////
// CMValue
extern "C" void _assign_svalue_no_free(svalue_t *,svalue_t *);
extern "C" void _free_svalue(svalue_t *,char *);

class CMValue : 
	public CComDualImpl<IMValue,   &IID_IMValue,   &LIBID_MUDOSLib>, 
	public CComDualImpl<IMNumber,  &IID_IMNumber,  &LIBID_MUDOSLib>, 
	public CComDualImpl<IMString,  &IID_IMString,  &LIBID_MUDOSLib>, 
	public CComDualImpl<IMReal,    &IID_IMReal,    &LIBID_MUDOSLib>, 
	public CComDualImpl<IMObject,  &IID_IMObject,  &LIBID_MUDOSLib>, 
	public CComDualImpl<IMArray,   &IID_IMArray,   &LIBID_MUDOSLib>, 
	public CComDualImpl<IMMapping, &IID_IMMapping, &LIBID_MUDOSLib>, 
	public CComDualImpl<IMClass,   &IID_IMClass,   &LIBID_MUDOSLib>, 
	public CComDualImpl<IMBuffer,  &IID_IMBuffer,  &LIBID_MUDOSLib>, 
	public CComObjectRoot,
	public CComCoClass<CMValue,&CLSID_MValue>
{
private:
	int       m_id;
	svalue_t  *parent;
	svalue_t  st;

	svalue_t * iGetSValue()
	{
		svalue_t *p;
		if(m_id<0)return NULL;
		if(parent){
			switch(parent->type){
			case T_ARRAY:
				if(!parent->u.arr)return NULL;
				if(m_id>=parent->u.arr->size)return NULL;
				p=&parent->u.arr->item[m_id];
				break;

			case T_OBJECT:
				if(!parent->u.ob)return NULL;
				if(m_id>=parent->u.ob->prog->num_variables_total)return NULL;
				p=&parent->u.ob->variables[m_id];
				break;

			case T_CLASS:
				if(!parent->u.cls)return NULL;
				if(m_id>=parent->u.cls->size)return NULL;
				p=&parent->u.cls->item[m_id];
				break;

			default: return NULL;
			}
		} else {
			p=&st;
		}
		return p;
	}
public:
	VALUETYPE Type();
	CMValue() {parent=NULL;st.type=0;st.subtype=0;st.u.number=0;m_id=-1;}
	void CreateRef(svalue_t *p,int id){
		if(m_id>=0)return;
		if(!(p->type&T_REFED))return;
		parent=p;
		m_id=id;
		if(!iGetSValue()){
			m_id=-1;
			parent=NULL;
			return;
		}
		if(parent->type==T_CLASS)parent->u.cls->ref++;
		if(parent->type==T_OBJECT)parent->u.ob->ref++;
		if(parent->type==T_ARRAY)parent->u.arr->ref++;
		if(parent->type==T_MAPPING)parent->u.arr->ref++;
	}
	void Create(svalue_t *s){
		if(m_id>=0)return;
		if(st.type!=0)_free_svalue(&st,"Create");
		_assign_svalue_no_free(&st,s);
		m_id=0;
	}
	void Assign(CMValue *v){
		if(m_id>=0)return;
		if(v->m_id<0)return;
		if(v->parent){
			CreateRef(v->parent,v->m_id);
		} else {
			Create(&v->st);
		}
	}
	~CMValue() {
		if(st.type!=0)_free_svalue(&st,"~CMValue");
		if(parent){
			_free_svalue(parent,"~CMValue");
		}
	}
	svalue_t * GetSValue(){
		svalue_t *p;
		p=iGetSValue();
		if(!p)return &st;
		return p;
	}
BEGIN_COM_MAP(CMValue)
	COM_INTERFACE_ENTRY2(IDispatch,IMValue)
	COM_INTERFACE_ENTRY(IMValue)
	COM_INTERFACE_ENTRY(IMNumber)
	COM_INTERFACE_ENTRY(IMString)
	COM_INTERFACE_ENTRY(IMReal)
	COM_INTERFACE_ENTRY(IMArray)
	COM_INTERFACE_ENTRY(IMMapping)
	COM_INTERFACE_ENTRY(IMClass)
	COM_INTERFACE_ENTRY(IMObject)
	COM_INTERFACE_ENTRY(IMBuffer)
END_COM_MAP()
//DECLARE_NOT_AGGREGATABLE(CMValue) 
// Remove the comment from the line above if you don't want your object to 
// support aggregation. 

DECLARE_REGISTRY(CMValue, _T("Mudos.Value.1"), _T("Mudos.Value"), IDS_MVALUE_DESC, THREADFLAGS_BOTH)

public:
	STDMETHOD(get_Program)(/*[out, retval]*/ IMProgram * *pVal);
	STDMETHOD(get_Extend)(/*[out, retval]*/ IDispatch * *pVal);
// IMValue
	STDMETHOD(CreateNumber)();
	STDMETHOD(CreateString)();
	STDMETHOD(CreateReal)();
	STDMETHOD(CreateArray)(int size);
	STDMETHOD(CreateMapping)();
	STDMETHOD(get_Type)(/*[out, retval]*/ VALUETYPE *pVal);
	STDMETHOD(get_Name)(/*[out, retval]*/ BSTR *pVal);

// IMNumber
	STDMETHOD(get_Number)(/*[out, retval]*/ int *pVal);
	STDMETHOD(put_Number)(/*[in]*/ int newVal);

// IMString
	STDMETHOD(get_String)(/*[out, retval]*/ BSTR *pVal);
	STDMETHOD(put_String)(/*[in]*/ BSTR newVal);

// IMReal
	STDMETHOD(get_Real)(/*[out, retval]*/ float *pVal);
	STDMETHOD(put_Real)(/*[in]*/ float newVal);

// IMArray
	STDMETHOD(get_ItemCount)(/*[out, retval]*/ int *pVal);
	STDMETHOD(get_Item)(/*[in]*/ int id, /*[out, retval]*/ IMValue * *pVal);
	STDMETHOD(get_NewItem)(/*[out, retval]*/ IMValue * *pVal);

// IMClass
	STDMETHOD(get_MemberCount)(/*[out, retval]*/ int *pVal);
	STDMETHOD(get_Member)(/*[in]*/ int id, /*[out, retval]*/ IMValue * *pVal);

// IMObject
	STDMETHOD(get_ObjectName)(/*[out, retval]*/ BSTR *pVal);
	STDMETHOD(get_ObjectLoadTime)(/*[out, retval]*/ int *pVal);
	STDMETHOD(get_Environment)(/*[out, retval]*/ IMObject * *pVal);
	STDMETHOD(get_Value)(/*[in]*/ int id, /*[out, retval]*/ IMValue * *pVal);
	STDMETHOD(get_ValueCount)(/*[out, retval]*/ int *pVal);
// IMMapping
	STDMETHOD(Map)(/*[in]*/ BSTR sKey,/*[in]*/ IDispatch * pVal);
	STDMETHOD(Query)(/*[in]*/ BSTR sKey, /*[out retval]*/ IMValue * * pVal);
	STDMETHOD(get_MappingKeys)(/*[out, retval]*/ IMArray * *pVal);
	STDMETHOD(get_MappingCount)(/*[out, retval]*/ int *pVal);
};

#endif // !defined(AFX_MVALUE_H__1B6ED7CB_EB38_11D1_BF0B_0000B4560A15__INCLUDED_)
